package com.yn.iotxiao.authorize;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yn.iotxiao.dotnet.DotNetUser;
import com.yn.iotxiao.dotnet.HttpContext;
import com.yn.iotxiao.response.AuthorizeException;
import com.yn.iotxiao.sql.entity.User.User;
import com.yn.iotxiao.sql.services.UserService;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.lang.reflect.Method;
@Slf4j
@Component
public class JWTInterceptor implements HandlerInterceptor {
    @Autowired
    UserService user;
    // 请求前到达之前拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object)
            throws Exception {
        // 从请求头获取 token
        String token = request.getHeader("Authorization");
        //首先映射是不是方法，如果不是则返回
        if(!(object instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod=(HandlerMethod) object;
        Method method=handlerMethod.getMethod();
        //检查是否有passtoken注释，有则跳过认证
//        if (method.isAnnotationPresent(PassToken.class)) {
//            PassToken passToken = method.getAnnotation(PassToken.class);
//            if (passToken.required()) {
//                return true;
//            }
//        }

        // token 验证失败后的返回信息
        if (method.isAnnotationPresent(Authorize.class)) {
            Authorize userLoginToken = method.getAnnotation(Authorize.class);
            if (userLoginToken.required()) {
                if (token == null || token.isEmpty()) {
                    throw new AuthorizeException( "无token，请重新登录");
                }
                // 获取 token 中的 user id
                String uid;
                var headers = request.getHeaderNames();
                while (headers.hasMoreElements()) {
                    log.info("header:" + headers.nextElement());
                }
                String type = request.getHeader("AuthorizationType");

                if (!StringUtils.isBlank(type) && type.equals("dotnet")) {
                    log.info("dotnet  token authorize");
//                    try {
//
//                    }catch (Exception e) {
//                        throw new  AuthorizeException("401");
//                    }
                    DotNetUser user = HttpContext.getUserFromToken(token);
                    if (user == null || StringUtils.isBlank(user.getUid())) {
                        throw new AuthorizeException("401：认证失败");
                    }
                    uid = user.getUid();


                }else {
                    log.info("java  token authorize");
                    try {
                        DecodedJWT decode = JWT.decode(token.replace("Bearer ",""));
                        uid = decode.getClaim("uid").asString();
                    } catch (JWTDecodeException j) {
                        throw new AuthorizeException("401");
                    }
                }

                User users = user.getWithUid(uid);
                log.info("uid:" + uid);
                if (users == null) {
                    log.info("用户不存在");
                    throw new AuthorizeException("用户不存在，请重新登录");
                }
                if (StringUtils.isBlank(type)) {
                    try {
                        Algorithm algorithm = Algorithm.HMAC256(users.getPassword());
                        JWTVerifier jwtVerifier = JWT.require(algorithm).withClaim("name", users.getName())
                                .withClaim("uid",uid).build();
                        // JWT 工具包验证 token
                        jwtVerifier.verify(token.replace("Bearer ",""));
                        return true;
                    } catch (TokenExpiredException e) {
                        throw new AuthorizeException("Token已经过期!!!");
                    } catch (SignatureVerificationException e){
                        throw new AuthorizeException("签名错误!!!");
                    } catch (AlgorithmMismatchException e){
                        throw new AuthorizeException("加密算法不匹配!!!");
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new AuthorizeException("无效token~~");
                    }
                }

            }
        }
        return true;
    }
}
